#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "led.h"


led_obj_t* led1_obj = NULL;
led_obj_t* led2_obj = NULL;

int8_t led_delete(led_obj_t* led_obj);

/**
 * @brief LED闪烁任务回调函数
 * @param arg LED对象
 * @return 无
 */
static void led_blink_task_callback(void* arg)
{
    if(!arg)
    {
        return;
    }
    led_obj_t* led_obj = (led_obj_t*)arg;
    while(1)
    {
        if(led_obj->data.current % 2 == 0)
        {
            gpio_set_level(led_obj->init.led_num, 0);
        }
        else
        {
            gpio_set_level(led_obj->init.led_num, 1);
        }
        led_obj->data.current++;
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}


/**
 * @brief LED任务回调函数
 * @param arg LED对象
 * @return 无
 */
static void led_task_callback(void* arg)
{
    if(!arg)    
    {
        return;
    }
    led_obj_t* led_obj = (led_obj_t*)arg;
    while(1)
    {
        if(led_obj->ctrl.led_state == LED_ON)
        {
            if(led_obj->blink_task_handle!= NULL)
            {
                vTaskDelete(led_obj->blink_task_handle);
                led_obj->blink_task_handle = NULL;
            }
            gpio_set_level(led_obj->init.led_num, 1);
        }
        else if(led_obj->ctrl.led_state == LED_OFF)
        {
            if(led_obj->blink_task_handle!= NULL)
            {
                vTaskDelete(led_obj->blink_task_handle);
                led_obj->blink_task_handle = NULL;
            }
            gpio_set_level(led_obj->init.led_num, 0);
        }
        else if(led_obj->ctrl.led_state == LED_BLINK)
        {
            //开启新线程，定时闪烁
            if(led_obj->blink_task_handle == NULL)
            {
                xTaskCreate(led_blink_task_callback, "blink", 2048, (void * const)led_obj, 5, &led_obj->blink_task_handle);
            }
        }
        xQueueReceive(led_obj->queue, &led_obj->ctrl.led_state, portMAX_DELAY);
    }
}

/**
 * @brief LED 初始化函数
 * @param led_num 要初始化的LED编号
 * @return 0 成功 -1 失败
 */
static led_obj_t* led_create(uint8_t led_num,led_state_t default_sts)
{
    led_obj_t* led_obj = (led_obj_t*)pvPortMalloc(sizeof(led_obj_t));
    memset(led_obj, 0, sizeof(led_obj_t));
    if(led_obj)
    {
        const gpio_config_t io_conf = {
        .pin_bit_mask = 1ULL << led_num,
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE,
        };

        gpio_config(&io_conf);

        led_obj->init.led_num = led_num;
        led_obj->ctrl.led_state = default_sts;
        led_obj->data.current = 0;

        led_obj->queue = xQueueCreate(3, sizeof(uint8_t));
        xTaskCreate(led_task_callback, "led_task", 2048, led_obj, 5, &led_obj->task_handle);
    }
    return led_obj;
}

/**
 * @brief LED APP初始化函数
 * @return 无
 */
void led_app_main(void) 
{
    led1_obj = led_create(BSP_LED1_GPIO, LED_OFF);
    led2_obj = led_create(BSP_LED2_GPIO, LED_OFF);
}

/**
 * @brief LED控制函数
 * @param led_obj LED对象
 * @param state LED状态
 * @return 0 成功 -1 失败  
 */
int8_t led_ctrl(led_obj_t* led_obj, led_state_t state)
{
    if((!led_obj) || (led_obj->queue == NULL))
    {
        return -1;
    }
    xQueueSend(led_obj->queue, &state, 0);
    return 0;
}

/**
 * @brief LED删除函数
 * @param led_obj LED对象
 * @return 0 成功 -1 失败 
 */
int8_t led_delete(led_obj_t* led_obj)
{
    if(!led_obj)
    {
        return -1;
    }
    vTaskDelete(led_obj->task_handle);
    vTaskDelete(led_obj->blink_task_handle);
    vQueueDelete(led_obj->queue);
    vPortFree(led_obj);
    return 0;
}
